/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tools.idea.streaming.core

import java.awt.event.MouseWheelEvent
import org.jetbrains.annotations.VisibleForTesting

/**
 * Returns the scroll amount normalized to feel natural.
 *
 * @param touchscreenScalingFactor the ratio between the size of the device display and the size in logical
 *        pixels of its projection on the host screen. Used only for the synthetic wheel events generated
 *        by touchscreens.
 */
internal fun MouseWheelEvent.getNormalizedScrollAmount(touchscreenScalingFactor: Double): Double {
  return when (scrollType) {
    MouseWheelEvent.WHEEL_UNIT_SCROLL -> adjustedWheelRotation * scrollAmount * ANDROID_SCROLL_ADJUSTMENT_FACTOR
    MouseWheelEvent.WHEEL_BLOCK_SCROLL -> 1.0
    // Wheel events generated by touch screens have scrollType = 3 that is neither WHEEL_UNIT_SCROLL, nor WHEEL_BLOCK_SCROLL.
    else -> preciseWheelRotation * scrollAmount / touchscreenScalingFactor * TOUCH_SCREEN_ADJUSTMENT_FACTOR
  }
}

/**
 * Returns a value between [MouseWheelEvent.preciseWheelRotation] and [MouseWheelEvent.wheelRotation]
 * interpolated using [PRECISE_WHEEL_ROTATION_WEIGHT].
 */
private val MouseWheelEvent.adjustedWheelRotation: Double
  get() = preciseWheelRotation * PRECISE_WHEEL_ROTATION_WEIGHT + wheelRotation * (1.0 - PRECISE_WHEEL_ROTATION_WEIGHT)

/** This is how much we want to adjust the mouse scroll for Android. This number was chosen empirically. */
@VisibleForTesting
internal const val ANDROID_SCROLL_ADJUSTMENT_FACTOR = 1 / 3.0
private const val TOUCH_SCREEN_ADJUSTMENT_FACTOR = 0.02
private const val PRECISE_WHEEL_ROTATION_WEIGHT = 0.02
